package com.wei.czz.framework.game.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import com.wei.czz.common.annotation.Auth;
import com.wei.czz.common.annotation.Resubmit;
import com.wei.czz.common.dto.common.NameValue;
import com.wei.czz.common.dto.game.GamePrizeDto;
import com.wei.czz.common.jsr303.group.OrderSearch;
import com.wei.czz.common.po.game.GamePo;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.tool.Result;
import com.wei.czz.common.vo.game.DeleteGamePrizeVo;
import com.wei.czz.common.vo.game.GamePrizeFormVo;
import com.wei.czz.common.vo.game.GamePrizeVo;
import com.wei.czz.common.vo.game.UpdateGamePrizeStatusVo;
import com.wei.czz.framework.common.service.AsyncService;
import com.wei.czz.framework.game.service.GameService;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import com.wei.czz.framework.game.service.GamePrizeService;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2023-03-16 11:36:29
 * className: GamePrizeController 游戏奖品请求接口类
 * version: 1.0
 * description:
 */
@RestController
@RequestMapping("/game-prize")
@AllArgsConstructor
public class GamePrizeController {

    private static final Logger log = LoggerFactory.getLogger(GamePrizeController.class);

    private final GamePrizeService gamePrizeService;

    private final GameService gameService;

    private final AsyncService asyncService;

    /**
     * 保存游戏奖品接口
     * <p>
     * 调用方：
     *  1、浏览器-后台管理页-游戏奖品管理页-游戏奖品添加/修改弹出框调用
     * <p>
     * 此接口会校验是否重复提交
     * @param gamePrizeVo 参数对象
     */
    @Resubmit(message = "保存游戏奖品")
    @PostMapping("/save")
    @Auth(permit = "game:prize:save")
    public Result<Object> saveGamePrize(@RequestBody GamePrizeVo gamePrizeVo){
        log.info("开始保存游戏奖品业务。{}", gamePrizeVo);
        if (gamePrizeVo.isSaveParamsFail()) {
            log.info("保存游戏奖品接口，请求参数错误");
            return Result.paramFail();
        }

        gamePrizeService.saveGamePrize(gamePrizeVo);

        log.info("保存游戏奖品业务结束");
        return Result.success();
    }

    /**
     * 初始化游戏奖品池接口
     * <p>
     * 调用方：
     *  1、浏览器-后台管理页-游戏奖品管理页调用
     * <p>
     * 此接口会校验是否重复提交
     * @param gamePrizeVo 参数对象
     */
    @Resubmit(message = "初始化游戏奖品池")
    @PostMapping("/init/pool")
    @Auth(permit = "game:prize:save")
    public Result<Object> initGamePrizePool(@RequestBody GamePrizeVo gamePrizeVo) {
        log.info("开始初始化游戏奖品池业务。{}", gamePrizeVo);
        if (Objects.isNull(gamePrizeVo.getGameId())) {
            log.info("初始化游戏奖品池接口，请求参数错误");
            return Result.paramFail();
        }

        gamePrizeService.initGamePrizePool(gamePrizeVo.getGameId());

        log.info("初始化游戏奖品池业务结束");
        return Result.success();
    }

    /**
     * 分页查询游戏奖品接口
     * <p>
     * 调用方：
     *  1、浏览器-后台管理页-游戏奖品管理页调用
     *
     * @param gamePrizeFormVo 参数对象
     * @return 游戏奖品分页数据
     */
    @PostMapping("/page/list")
    @Auth(permit = "game:prize:list")
    public Result<Map<String, Object>> pageGamePrizeList(@Validated(OrderSearch.class) @RequestBody GamePrizeFormVo gamePrizeFormVo){
        log.info("开始分页查询游戏奖品业务。{}", gamePrizeFormVo);

        CompletableFuture<Integer> totalProbabilityFuture = asyncService.supplyAsync(
                () -> gamePrizeService.getTotalProbability(gamePrizeFormVo.getGameId())
        );
        CompletableFuture<GamePo> gamePoFuture = asyncService.supplyAsync(
                () -> gameService.getGamePo(gamePrizeFormVo.getGameId())
        );

        PageDto<GamePrizeDto> pageDto = gamePrizeService.pageGamePrizeList(gamePrizeFormVo);

        Map<String, Object> data = new HashMap<>();
        data.put("page", pageDto);
        try {
            Integer totalProbability = totalProbabilityFuture.get();
            data.put("totalProbability", totalProbability);
        } catch (InterruptedException | ExecutionException e) {
            log.error("查询游戏奖品总中奖概率失败", e);
        }
        try {
            GamePo gamePo = gamePoFuture.get();
            data.put("defaultPrizeId", gamePo.getDefaultPrizeId().toString());
        } catch (InterruptedException | ExecutionException e) {
            log.error("查询游戏奖品失败", e);
        }
        log.info("分页查询游戏奖品业务结束");
        return Result.success(data);
    }

    /**
     * 获取游戏奖品列表接口
     * 只查询简单数据
     * <p>
     * 调用方：
     *  1、浏览器-后台管理页-游戏管理页-游戏流水弹出框调用
     *
     * @param gameId 游戏主键
     * @return 游戏奖品列表
     */
    @GetMapping("/simple/list")
    @Auth(permit = "game:list")
    public Result<List<NameValue<String>>> getSimpleGamePrizeList(@RequestParam("gameId") Long gameId) {
        log.info("开始获取游戏奖品列表业务。gameId={}", gameId);

        List<NameValue<String>> prizeList = gamePrizeService.getSimpleGamePrizeList(gameId);

        log.info("获取游戏奖品列表业务结束");
        return Result.success(prizeList);
    }

    /**
     * 获取游戏奖品下一个排序等级接口
     * <p>
     * 调用方：
     *  1、浏览器-后台管理页-游戏奖品管理页-游戏奖品添加/修改弹出框调用
     *
     * @param gameId 游戏主键
     * @return 排序等级
     */
    @GetMapping("/next/sort")
    @Auth(permit = "game:prize:get")
    public Result<Integer> getNextSort(@RequestParam("gameId") Long gameId) {
        log.info("开始获取游戏奖品下一个排序等级业务。gameId={}", gameId);

        Integer nextSort = gamePrizeService.getNextSort(gameId);

        log.info("获取游戏奖品下一个排序等级业务结束");
        return Result.success(nextSort);
    }

    /**
     * 修改游戏奖品接口
     * <p>
     * 调用方：
     *  1、浏览器-后台管理页-游戏奖品管理页-游戏奖品添加/修改弹出框调用
     * <p>
     * 此接口会校验是否重复提交
     * @param gamePrizeVo 参数对象
     */
    @Resubmit(message = "修改游戏奖品")
    @PostMapping("/update")
    @Auth(permit = "game:prize:update")
    public Result<Object> updateGamePrize(@RequestBody GamePrizeVo gamePrizeVo){
        log.info("开始修改游戏奖品业务。{}", gamePrizeVo);
        if (gamePrizeVo.isUpdateParamsFail()) {
            log.info("修改游戏奖品接口，请求参数错误");
            return Result.paramFail();
        }

        gamePrizeService.updateGamePrize(gamePrizeVo);

        log.info("修改游戏奖品业务结束");
        return Result.success();
    }

    /**
     * 修改游戏奖品状态接口
     * <p>
     * 调用方：
     *  1、浏览器-后台管理页-游戏奖品管理页调用
     * <p>
     * 此接口会校验是否重复提交
     * @param updateStatusVo 参数对象
     */
    @Resubmit(message = "修改游戏奖品状态")
    @PostMapping("/update/status")
    @Auth(permit = "game:prize:update")
    public Result<Object> updateGameStatus(@Validated @RequestBody UpdateGamePrizeStatusVo updateStatusVo) {
        log.info("开始修改游戏奖品状态业务。{}", updateStatusVo);

        gamePrizeService.updateGamePrizeStatus(updateStatusVo);

        log.info("修改游戏奖品状态业务结束");
        return Result.success();
    }

    /**
     * 删除游戏奖品接口
     * <p>
     * 调用方：
     *  1、浏览器-后台管理页-游戏奖品管理页调用
     * <p>
     * 此接口会校验是否重复提交
     * @param deleteGamePrizeVo 参数对象
     */
    @Resubmit(message = "删除游戏奖品")
    @RequestMapping("/delete")
    @Auth(permit = "game:prize:delete")
    public Result<Object> deleteGamePrize(@RequestBody DeleteGamePrizeVo deleteGamePrizeVo){
        log.info("开始删除游戏奖品业务。{}", deleteGamePrizeVo);
        if (deleteGamePrizeVo.isParamsFail()) {
            log.info("删除游戏奖品接口，请求参数错误");
            return Result.paramFail();
        }

        gamePrizeService.deleteGamePrize(deleteGamePrizeVo);

        log.info("删除游戏奖品业务结束");
        return Result.success();
    }

}
